#include "stdafx.h"

#if _WIN32_WCE==200

extern LPWSTR str2Wstr( LPCSTR lpszStr, size_t * lpCount = NULL);

extern "C" int core200__vsnprintf(char *buffer, size_t count, const char * format, va_list argptr )
{
	OutputDebugString(_T("_vsnprintf: "));

	LPWSTR pFormatW = str2Wstr( format );

	if (NULL == pFormatW)
		return 0;

	LPWSTR pCharW = pFormatW;
	while ( *pCharW != 0 )
	{
		if (*pCharW == _T('%'))
		{
			pCharW++;

			if (*pCharW == _T('s')) 
				*pCharW =  _T('S');
		}

		pCharW++;
	}

	OutputDebugString(pFormatW);
	OutputDebugString(_T("\n"));

	int ret = 0;

	LPWSTR pBufW = (LPWSTR) malloc( (count+1)*2 );
	if (NULL != pBufW)
	{
		wvsprintf( pBufW, pFormatW, argptr );

		OutputDebugString(pBufW);
		OutputDebugString(_T("\n"));

		ret = wcstombs( buffer, pBufW, count );

		free( pBufW );
	}

	free( pFormatW );

	return ret;
}

extern "C" int core200_sprintf( char *buffer, const char *format, ... )
{ 
	OutputDebugString(_T("sprintf\n")); 

	va_list argptr;
	va_start(argptr, format);

	return core200__vsnprintf( buffer, 1024, format, argptr );
}

extern "C" int core200__vsnwprintf( wchar_t *buffer, size_t count, const wchar_t *format, va_list argptr )
{ 
	OutputDebugString(_T("_vsnwprintf: ")); 


/*	TCHAR buf[100];
	int i = va_arg( argptr, int );
	swprintf( buf, _T(" i=%d"), i );
	OutputDebugString(buf);

	TCHAR* str = va_arg( argptr, TCHAR* );
	swprintf( buf, _T(" s=%s"), str );
	OutputDebugString(buf);
*/
	
// the (%.*) or (%.n) are not implemented

	OutputDebugString(format); 

	int res;

	if ( 0==wcscmp( _T("%.*s%.*s"), format ) )
	{
		int count; LPCWSTR str1, str2;

		count = va_arg( argptr, int );
		str1  = va_arg( argptr, LPCWSTR );
		count = va_arg( argptr, int );
		str2  = va_arg( argptr, LPCWSTR );

		res = wsprintf( buffer, _T("%s%s"), str1, str2 );
	}
	else if ( 0==wcscmp( _T("%d%.*s"), format ) )
	{
		int n, count; LPCWSTR str1;

		n     = va_arg( argptr, int );
		count = va_arg( argptr, int );
		str1  = va_arg( argptr, LPCWSTR );

		res = wsprintf( buffer, _T("%d%s"), n, str1 );
	}
	else
	{
		res = wvsprintf( buffer, format, argptr );
	}

	OutputDebugString(_T(" -> ")); 
	OutputDebugString(buffer); 
	OutputDebugString(_T("\n")); 

	return res;
}

extern "C" int core200_wprintf( const wchar_t *format, ... )
{ 
#ifdef DEBUG
	OutputDebugString(_T("wprintf: ")); 
	OutputDebugString(format); 

	va_list argptr;
	va_start(argptr, format);

	wchar_t buffer[1024*2];
	int res = wvsprintf( buffer, format, argptr );

	OutputDebugString(_T(" -> "));
	OutputDebugString(buffer);
	OutputDebugString(_T("\n"));

	return res;
#else
	return 0;
#endif
}

extern "C" int core200_toupper( int c )
{
#ifdef DEBUG
	OutputDebugString(_T("toupper: "));

	TCHAR ch[2]; ch[0]=c; ch[1]=0;
	OutputDebugString( ch );
	OutputDebugString(_T(" to "));
#endif

	int cRet = towupper( c ) & 0xFF;

#ifdef DEBUG
	ch[0]=cRet;
	OutputDebugString( ch );
	OutputDebugString(_T("\n"));
#endif

	return cRet;
}

struct core200_FILE 
{
	HANDLE hFile;
	BOOL bText;
};

extern "C" core200_FILE *core200__wfopen( const wchar_t *filename, const wchar_t *mode )
{
	OutputDebugString(_T("_wfopen: ")); 
	OutputDebugString( filename );
	OutputDebugString(_T(" : "));
	OutputDebugString( mode );
	OutputDebugString(_T("\n")); 

	DWORD dwDesiredAccess						= 0;
	DWORD dwShareMode							= 0;
	LPSECURITY_ATTRIBUTES lpSecurityAttributes	= NULL;
	DWORD dwCreationDisposition					= 0;
	DWORD dwFlagsAndAttributes					= FILE_ATTRIBUTE_NORMAL;
	HANDLE hTemplateFile						= NULL;

	BOOL bAppend = false;
	BOOL bText   = false;
	
	for (wchar_t ch = *mode; ch != 0; mode++, ch = *mode)
	{
		switch (ch)
		{
		case L'r':
			dwDesiredAccess       = GENERIC_READ;
			dwCreationDisposition = OPEN_EXISTING;
			break;

		case L'w':
			dwDesiredAccess       = GENERIC_WRITE;
			dwCreationDisposition = TRUNCATE_EXISTING;
			break;

		case L'a':
			dwDesiredAccess       = GENERIC_WRITE;
			dwCreationDisposition = OPEN_ALWAYS;
			bAppend = true;
			break;

		case L'+':
			dwDesiredAccess       = GENERIC_READ | GENERIC_WRITE;
			break;

		case L'c':
			dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
			break;

		case L't':
			bText = true;
			break;
		}
	}
	
	core200_FILE * pFile = (core200_FILE*) malloc( sizeof(core200_FILE) );
	if (NULL == pFile) return NULL;

	pFile->bText = bText;
	pFile->hFile = CreateFile(
		  filename
		, dwDesiredAccess
		, dwShareMode
		, lpSecurityAttributes
		, dwCreationDisposition
		, dwFlagsAndAttributes
		, hTemplateFile );

	if (pFile->hFile == INVALID_HANDLE_VALUE)
	{
		free(pFile);
		return NULL;
	}

	if ( bAppend )
	{
		SetFilePointer( pFile->hFile, 0, 0, FILE_END );
	}

	return pFile;
}

extern "C" core200_FILE* core200_fopen(const char *filename, const char *mode)
{
	core200_FILE* ret = NULL;

	LPWSTR wfilename = str2Wstr( filename );
	LPWSTR wmode     = str2Wstr( mode );

	if ((NULL != wfilename) && (NULL != wmode))
		ret = core200__wfopen(wfilename, wmode);

	if (NULL != wfilename) free( wfilename );
	if (NULL != wmode    ) free( wmode );

	return ret;

/*
//	TCHAR wfilename[MAX_PATH];
//	if (-1 == mbstowcs( wfilename, filename, __min(MAX_PATH, strlen( filename )) ))
//		return NULL;

	LPWSTR wfilename = str2Wstr( filename );
	if (NULL == wfilename)
		return NULL;

#if DEBUG
	TCHAR wmode[10];
	mbstowcs( wmode, mode, strlen( mode ) );

	OutputDebugString(_T("fopen: ")); 
	OutputDebugString( wfilename );
	OutputDebugString(_T(" : "));
	OutputDebugString( wmode );
	OutputDebugString(_T("\n")); 
#endif

	DWORD dwDesiredAccess						= 0;
	DWORD dwShareMode							= 0;
	LPSECURITY_ATTRIBUTES lpSecurityAttributes	= NULL;
	DWORD dwCreationDisposition					= 0;
	DWORD dwFlagsAndAttributes					= FILE_ATTRIBUTE_NORMAL;
	HANDLE hTemplateFile						= NULL;

	BOOL bAppend = false;
	BOOL bText   = false;
	
	for (char ch = *mode; ch != 0; mode++, ch = *mode)
	{
		switch (ch)
		{
		case 'r':
			dwDesiredAccess       = GENERIC_READ;
			dwCreationDisposition = OPEN_EXISTING;
			break;

		case 'w':
			dwDesiredAccess       = GENERIC_WRITE;
			dwCreationDisposition = TRUNCATE_EXISTING;
			break;

		case 'a':
			dwDesiredAccess       = GENERIC_WRITE;
			dwCreationDisposition = OPEN_ALWAYS;
			bAppend = true;
			break;

		case '+':
			dwDesiredAccess       = GENERIC_READ | GENERIC_WRITE;
			break;

		case 't':
			bText = true;
			break;

		case 'b':
			break;

		case 'c':
			dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
			break;

		case 'n':
			break;

		}
	}
	
	core200_FILE * pFile = (core200_FILE*) malloc( sizeof(core200_FILE) );
	if (NULL != pFile)
	{
		pFile->bText = bText;
		pFile->hFile = CreateFile(
			  wfilename
			, dwDesiredAccess
			, dwShareMode
			, lpSecurityAttributes
			, dwCreationDisposition
			, dwFlagsAndAttributes
			, hTemplateFile );

		if (pFile->hFile == INVALID_HANDLE_VALUE)
		{
			free(pFile);
			pFile = NULL;
		}
		else if ( bAppend )
		{
			SetFilePointer( pFile->hFile, 0, 0, FILE_END );
		}
	}

	free( wfilename );

	return pFile;
*/
}

extern "C" size_t core200_fread( void *buffer, size_t size, size_t count, core200_FILE *stream )
{
	OutputDebugString(_T("fread\n")); 

	if (0 == count || 0 == size ) return 0;

	if ( stream->bText )
	{
		size_t nBytesToRead = size * count;

		nBytesToRead = nBytesToRead / sizeof( wchar_t );


		char* buf = (char*) malloc( nBytesToRead );

		// read multibyte stream
		DWORD dwRead;
		ReadFile( stream->hFile, buf, nBytesToRead, &dwRead, NULL );

		// convert to unicode
		size_t nConverted = mbstowcs((wchar_t*) buffer, buf, dwRead );

		free(buf);
		
		return nConverted * sizeof( wchar_t ) / size;
	}
	else
	{
		size_t nBytesToRead = size * count;

		DWORD dwRead;
		ReadFile( stream->hFile, buffer, nBytesToRead, &dwRead, NULL );
		
		return dwRead / size;
	}
}

#define EOF (-1)
extern "C" int core200_fclose( core200_FILE *stream )
{
	OutputDebugString(_T("fclose\n")); 

	if ( CloseHandle( stream->hFile ) )
		return 0;
	else
		return EOF;
}

extern "C" int core200_fwprintf( core200_FILE *stream, const wchar_t *format, ... )
{
	OutputDebugString(_T("fwprintf: "));
	OutputDebugString( format );
	OutputDebugString(_T("\n"));

	va_list argptr;
	va_start(argptr, format);

	wchar_t wbuffer[2048];
	int nCharCount = core200__vsnwprintf( wbuffer, 2048, format, argptr );

	char buffer[2048];
	int nBytes = wcstombs( buffer, wbuffer, 2048 );

	DWORD dwBytesWritten = 0;
	
	if ( false == stream->bText )
	{
		if ( false == WriteFile( stream->hFile, buffer, nCharCount * sizeof(wchar_t), &dwBytesWritten, NULL ) )
			return -1;

		return dwBytesWritten / sizeof(wchar_t);
	}

	for (char* pBuffer = buffer; pBuffer<buffer+nCharCount; pBuffer++)
	{
		DWORD dw;
		if ( pBuffer[0] == '\n' )
		{
			const char chLineFeed = 13;
			WriteFile( stream->hFile, &chLineFeed, 1, &dw, NULL );
		}

		if (false == WriteFile( stream->hFile, pBuffer, 1, &dw, NULL ) )
			return -1;

		dwBytesWritten += dw;
	}

	return dwBytesWritten * sizeof(wchar_t);
}

extern "C" HCURSOR core200_SetCursor( HCURSOR hCursor )
{
#ifdef DEBUG
	TCHAR buf[300];
	swprintf( buf, _T("SetCursor: hCursor=0x%x\n"), hCursor );
	OutputDebugString(buf);
#endif

	// this system supports only IDC_WAIT cursor
	if ((HCURSOR)IDC_WAIT == hCursor )
		return SetCursor( hCursor );
	else
		return SetCursor( NULL );
}

extern "C" int core200_WSACleanup()
{
	OutputDebugString(_T("WSACleanup\n")); 
	return 0;
}

extern "C" int core200_WSAStartup()
{
	OutputDebugString(_T("WSAStartup\n")); 
	return 0;
}


#if MIPS
extern "C" int core200___ged(double a, double b)
{
	return a >= b;
}

extern "C" int core200___eqd(double a, double b)
{
	return a == b;
}

extern "C" int core200___eqs(float a, float b)
{
	return a == b;
}

extern "C" int core200___gtd(double a, double b)
{
	return a > b;
}

extern "C" int core200___ltd(double a, double b)
{
	return a < b;
}
#endif // MIPS

#endif // _WIN32_WCE==200
